
// ========================================================================================================================
// 此处为网络请求底层封装：
// 1、simpleRequest：api请求前并不会校验本地是否存在用户登录信息缓存（如Id、Token、WxSaId以及UUserId)
// 2、simepleRequestNoCheckResponse: api请求前不会校验本地是否存在用户登录信息缓存，响应成功后也不会校验返回的结果码ResultCode
// 3、request: 都会进行校验
// 其它：
// 1、如果需要测试新用户相关的逻辑：请将以下变量 isDebugNewUser 置为 true, 并清除微信环境的相关缓存变量（如授权信息、本地存储等） 
// ========================================================================================================================

// TODO 测试新用户注册逻辑
// 在发布前需要将相应测试代码注释（不注释并不会影响功能，只会影响性能）
// TODO 后续改进将需要使用发布脚本清除代码：待完成！！！！！！
var isDebugNewUser = false;

// 基础库 1.4.0 开始支持!!!
var requestTask = null;

var config = require('../config.js');
var myDebugger = require('../utils/myDebugger.js');

// ============================================================
// 常量
var API_PATH_OF_LOGIN = 'login' // 用户登录api
var API_PATH_OF_REGISTER = 'wx/xcxGetUserInfo' // 用户注册api
var RESULT_CODE_OF_NO_AUTH = '1011'

var CACHE_KEY_OF_AUTH_VO = '__CACHE_KEY_AUTH_VO__' // 用户认证信息缓存ke
var CACHE_KEY_OF_HAD_AUTH_GET_USER_INFO = '__CACHE_KEY_OF_HAD_AUTH_GET_USER_INFO__' // 用户是否同意授权获取用户信息key

// ============================================================
// 用户认证信息
var authVO = null;

function getCacheOfAuthVO() {
  if (!authVO) {
    // 同步获取用户的登录信息，并缓存
    try {
      var value = wx.getStorageSync(CACHE_KEY_OF_AUTH_VO);
      if (value) {
        authVO = value;
      }
    } catch (e) {
      myDebugger.error('获取缓存的用户认证信息失败:', e);
    }
  }
  return authVO || {};
};

function setCacheOfAuthVO(userAuthVO) {
  authVO = userAuthVO;
  try {
    wx.setStorageSync(CACHE_KEY_OF_AUTH_VO, userAuthVO);
  } catch (e) {
    myDebugger.error('缓存用户认证信息失败:', e);
  }
};

// ============================================================
// 用户授权小程序获取用户信息状态
function getCacheOfHadAuthGetUserInfo() {
  var state = 0
  try {
    var value = wx.getStorageSync(CACHE_KEY_OF_HAD_AUTH_GET_USER_INFO);
    state = value
  } catch (e) {
    myDebugger.error('获取用户是否曾授权小程序获取用户信息失败:', e);
  }
  return parseInt(state || 0)
};

function setCacheOfHadAuthGetUserInfo(state) {
  try {
    wx.setStorageSync(CACHE_KEY_OF_HAD_AUTH_GET_USER_INFO, state);
  } catch (e) {
    myDebugger.error('缓存用户是否曾授权小程序获取用户信息失败:', e);
  }
};

// ============================================================

// 显示加载中...
function showLoading(obj) {
  obj = obj || {};
  wx.showToast({
    title: obj.title || '加载中...',
    icon: obj.icon || 'loading',
    image: obj.image,
    duration: obj.duration || 30000,
    mask: obj.mask || true,
    success: obj.success,
    fail: obj.fail,
    complete: obj.complete
  })
  return this;
};

// 隐藏加载中...
function hideLoading(isRightNow) {
  if (isRightNow) {
    wx.hideToast();
    return;
  }
  setTimeout(function () {
    wx.hideToast();
  }, 300)

};

// 格式化请求地址
function formatApi(path) {
  return config.HOST + config.BASE_PATH + path
};

// 用户是否登录过
// callback {yes: function () {}, no: function() {}}
function checkIsLogin(callback) {
  if (typeof callback != 'object') {
    myDebugger.log('checkIsLogin\'s function param is error!')
    return;
  }
  var authVO = getCacheOfAuthVO();
  if (!authVO || !authVO.UUserId || authVO.UUserId <= 0) {
    // 微信登录：wx.login -> 开发者服务器login -> 注册过（UUserId > 0) => 授权wx.getUserInfo => 开发者服务器getUserInfo
    // 没有登录过
    callback.no();
  } else {
    // 已登录过，但未知道token是否过期     
    callback.yes();
  }
};

// 执行方法：主要用于处理请求后的反馈
// func请求反馈的处理方法（若不存在则执行defaultFunc), res请求返回的数据
function handleFunc(func, res, defaultFunc) {
  if (func && typeof func == 'function') {
    func(res);
  } else {
    defaultFunc && typeof defaultFunc == 'function' && defaultFunc(res);
  }
};

// 格式化请求参数
function formatReqParam(data) {
  data = data || {};
  // data.AppKey = config.APP_KEY;
  // data.ReqType = config.REQ_TYPE;

  // data.User = getCacheOfAuthVO() || {}
  return data;
};

// 微信请求
// callback: {success: Function, fail: Function, error: Function, complete: Function}
function wxRequest(options, callback) {
  var that = this
  options = options || {}
  var url = formatApi(options.api)
  var data = options.data || {}
  var isCheckResponse = true;
  var checkBeforeRequest = options.checkBeforeRequest;
  if (typeof checkBeforeRequest == 'function') {
    var authVO = getCacheOfAuthVO();
    var state = checkBeforeRequest(authVO);
    if (!state) return;
  }
  if (typeof options.isCheckResponse === 'boolean') {
    isCheckResponse = options.isCheckResponse
  }
  data = formatReqParam(data);
  callback = callback || {}
  requestTask = wx.request({
    url: url,
    data: data,
    method: 'POST',
    header: {
      'Content-Type': 'application/json'
    },
    success: function (res) {
      if (res.statusCode === 200) {
        var responseData = res.data;
        if (!isCheckResponse) {
          myDebugger.log('----------        直接返回数据，不做任何校验');
          return callback.success && callback.success(responseData)
        }
        if (responseData.ResultCode == RESULT_CODE_OF_NO_AUTH) {
          myDebugger.log('----------        登录过期,将执行重新登录');
          login({
            success: function () {
              myDebugger.log('----------        重新登录成功，再次获取数据');
              wxRequest(options, callback);
            }
          });
        } else {
          if (responseData.ResultCode == '0') {
            myDebugger.log('----------        服务器成功返回数据：响应正确');
            handleFunc(callback.success, responseData)
          } else {
            myDebugger.log('----------        服务器成功返回数据：响应出错');
            handleFunc(callback.fail, responseData, function () {
              hideLoading();
              wx.showModal({
                title: '提示',
                content: responseData.ResultMessage || '发生错误',
                showCancel: false
              });
            })
          }
        }
      } else {
        // 网络错误处理
        handleFunc(callback.error, {}, function () {
          handleWhenNewWorkError(options, callback)
        })
      }
    },
    fail: function () {
      // 网络错误处理
      handleFunc(callback.error, {}, function () {
        handleWhenNewWorkError(options, callback)
      })
    },
    complete: function () {
      requestTask = null;
      handleFunc(callback.complete, {}, function () {
        // hideLoading();
      })
    }
  })
};

// 缓存用户登录相关的信息
function cacheUserLoginState(userRes) {
  var authVO = {};
  var user = userRes.User;
  authVO.Id = user.Id;
  authVO.Token = user.Token;
  authVO.WxSaId = user.WxSaId;
  authVO.UUserId = user.UUserId;
  setCacheOfAuthVO(authVO);
};

// 登录
function login(callback) {
  var that = this;
  myDebugger.log('----------        微信登录');
  wx.login({
    success: function (wxLoginRes) {
      myDebugger.log('----------        微信登录成功', wxLoginRes);
      var data = {};
      data.code = wxLoginRes.code;
      devServerLogin(data, {
        success: function (devServerLoginRes) {
          cacheUserLoginState(devServerLoginRes);
          // 保存用户信息
            callback.success && callback.success()

          //   if (checkIsNewUser(devServerLoginRes.User)) {
          //   register(callback);
          // } else {
          //   callback.success && callback.success()
          // }
        }

      });
    },
    fail: function () {
      handleFunc(callback.fail, {}, function () {
        wx.showModal({
          title: '微信登录失败',
          content: '点击确定重试',
          success: function (res) {
            if (res.confirm) {
              login(callback);
            }
          }
        });
      });
    }
  })
}

// 发生网络错误时的处理
function handleWhenNewWorkError(options, callback) {
  var that = this;
  wx.showModal({
    title: '网络错误，请检查网络环境',
    content: '点击确定重试',
    success: function (res) {
      if (res.confirm) {
        wxRequest(options, callback);
      }
    }
  });
};

// 开发者服务器登录
function devServerLogin(data, callback) {
  var that = this;
  callback = callback || {};
  myDebugger.log('----------        开发者服务器登录');
  wxRequest({ api: API_PATH_OF_LOGIN, data: data }, {
    success: function (responseData) {
        myDebugger.log('----------        开发者服务器登录成功', responseData);

        handleFunc(callback.success, responseData);
    }
  })
};

// 检查是否为新用户
function checkIsNewUser(user) {
  // TODO 测试新用户注册逻辑
  if (isDebugNewUser) {
    return true;
  }
  return user && user.UUserId <= 0
}

// 注册统一身份
function register(callback) {
  myDebugger.log('----------       新用户进行注册中...');
  var that = this;
  var hadAuthGetUserInfo = getCacheOfHadAuthGetUserInfo()
  if (hadAuthGetUserInfo === 2) {
    if (wx.openSetting) {
      wx.openSetting({
        success: (res) => {
          setCacheOfHadAuthGetUserInfo(1);
          res.authSetting = {
            "scope.userInfo": true
          }
          getUserInfo(callback)
        },
        fail: () => {
          wx.showModal({
            title: '获取用户信息失败',
            content: '微点趣需要获取您的信息,点击确定重试，取消则无法正常使用',
            success: function (res) {
              if (res.confirm) {
                register(callback)
              }
            }
          });
        }
      })
    } else {
      // 如果希望用户在最新版本的客户端上体验您的小程序，可以这样子提示
      wx.showModal({
        title: '提示',
        content: '当前微信版本过低，无法使用该功能，请升级到最新微信版本后重试。'
      })
    }
  } else {
    getUserInfo(callback)
  }
}

// 小程序获取用户信息进而将数据发送给后台，获取用户的unicode-id（可以说是真正的注册）
function getUserInfo(callback) {
  var that = this;
  wx.getUserInfo({
    withCredentials: true,
    success: function (wxUserInfoRes) {
      myDebugger.log('----------        微信getUserInfo');
      var data = {}
      data.UserInfo = wxUserInfoRes.userInfo;
      data.RawData = wxUserInfoRes.rawData;
      data.Signature = wxUserInfoRes.signature;
      data.EncryptedData = wxUserInfoRes.encryptedData;
      data.Iv = wxUserInfoRes.iv;
      // 认证信息：id
      data.User = getCacheOfAuthVO()
      var options = { api: API_PATH_OF_REGISTER, data: data };
      // TODO 测试新用户注册逻辑
      if (isDebugNewUser) {
        options.isCheckResponse = false;
      }
      wxRequest(options, {
        success: function (devServerUserInfo) {
          myDebugger.log('----------        开发者服务器的获取用户信息（即注册）:', devServerUserInfo);
          // TODO 测试新用户注册逻辑
          if (isDebugNewUser) {
            setCacheOfHadAuthGetUserInfo(1);
            handleFunc(callback.success);
            return;
          }
          cacheUserLoginState(devServerUserInfo);
          setCacheOfHadAuthGetUserInfo(1);
          handleFunc(callback.success)
        }
      });
    },
    fail: function () {
      setCacheOfHadAuthGetUserInfo(2);
      handleFunc(callback.fail, {}, function () {
        hideLoading();
        wx.showModal({
          title: '提示',
          content: '请授权微点趣使用用户信息，该操作仅会获取您的昵称和头像，请放心授权',
          showCancel: false,
          confirmText: '我知道了',
          success: function (res) {
            if (res.confirm) {
              register(callback)
            }
          }
        });
      });
    }
  })
}

// 文件上传api
function uploadFile(apiPath, fileKey, filePath, callback, progressUpdateCallback) {
  callback = callback || {};
  var data = formatReqParam({});
  var requestTask = wx.uploadFile({
    url: formatApi(apiPath),
    filePath: filePath,
    name: fileKey,
    formData: {
      ImageUploadFileReq: JSON.stringify(data)
    },
    success: function (res) {
      myDebugger.log('==============================');
      myDebugger.log('upload file success ==========', res);
      var result = JSON.parse(res.data) || {};
      var resultCode = result.ResultCode;
      if (resultCode == RESULT_CODE_OF_NO_AUTH) {
        // token过期,重新登录
        myDebugger.log('----------        token过期,重新登录')
        login({
          success: function () {
            uploadFile(apiPath, fileKey, filePath, callback, progressUpdateCallback)
          }
        });
      } else {
        if (resultCode == 0) {
          handleFunc(callback.success, result);
        } else {
          handleFunc(callback.fail, result);
        }
      }
    },
    fail: function (res) {
      handleFunc(callback.error, res, function () {
        wx.showModal({
          title: '提示',
          content: '网络错误,请检查网络是否可用，若可用请点击重试',
          success: function (res) {
            if (res.confirm) {
              uploadFile(apiPath, fileKey, filePath, callback, progressUpdateCallback)
            }
          }
        })
      });
    },
    complete: function (res) {
      handleFunc(callback.complete, res);
    }
  });
  if (!requestTask) return;
  // 基础库 1.4.0 开始支持
  requestTask.onProgressUpdate((res) => {
    // console.log('上传进度', res.progress)
    // console.log('已经上传的数据长度', res.totalBytesSent)
    // console.log('预期需要上传的数据总长度', res.totalBytesExpectedToSend)
    progressUpdateCallback && progressUpdateCallback(res);
  })
  return requestTask
}



module.exports = {
  // 显示加载中
  showLoading: showLoading,
  // 隐藏加载中
  hideLoading: hideLoading,

  // 请求任务：1.4.0开始支持
  requestTask: requestTask,

  uploadFile: uploadFile,


  // 检查是否登录
  checkIsLogin: checkIsLogin,

  // 登录操作
  login: login,

  // 取消请求任务
  abortRequest: function () {
    requestTask && requestTask.abort();
  },

  // 获取用户登录信息
  getCacheOfAuthVO: getCacheOfAuthVO,

  // 网络请求：1、请求前不校验登录状态 2、响应后校验登录状态
  simpleRequest: wxRequest,

  // 网络请求：1、请求前不校验登录状态 2、响应后也不校验响应状态
  simpleRequestNoCheckResponse: function (options, callback) {
    options.isCheckResponse = false;
    wxRequest(options, callback);
  },

  // 网络请求：1、请求之前会进行登录校验 2、响应后也会进行状态码校验
  request: function (options, callback) {
    var that = this;
    callback = callback || {}
    checkIsLogin({
      yes: function () {
        myDebugger.log('----------        用户曾经登录过');
        wxRequest(options, callback);
      },
      no: function () {
        myDebugger.log('----------        用户从未登录过');
        login({
          success: function () {
            wxRequest(options, callback);
          }
        });
      }
    })
  }
}
